﻿using System.Text;
using CdgNetPersistencia.Componentes;
using System.Collections.Generic;
using System;
using System.Reflection;

/**
    * Autor :  Cristian Daniel Garay Sosa
    * Fecha :  26/03/2012 (v2)
    * Comentarios:
    *          almacena todo lo concerniente a una tabla
    * 
    * Cambios:
    *          26/03/2012 - CDGS - Sin cambios desde la version original
    * 
    * **/

namespace CdgNetPersistencia.ClasesBases
{
    /// <summary>
    /// Clase base de Datos de Tabla
    /// </summary>
    public abstract class TBLbase
    {
        
        #region PROPIEDADES

        public static string NOMBRE_TABLA = "";

        public static string DROP_SQL = "DROP TABLE IF EXISTS '{0}'";
        public static string CREATE_SQL = "";

        public const string SELECT_BASICO = "SELECT {0} {1} FROM {2} ";

        private const string __FILTRO_BASICO_INT = " WHERE {0}.{1} = {2}";
        private const string __FILTRO_BASICO_STRING = " WHERE {0}.{1} LIKE \'%{2}%\'";

        private const string __INSERT_SQL = "INSERT INTO {0} ({1}) VALUES ({2})";
        private const string __UPDATE_SQL = "UPDATE {0} SET {1} ";
        private const string __DELETE_SQL = "DELETE FROM {0} ";


        public Dictionary<string, CampoTabla> CAMPOS;

        

        #endregion



        #region CONSTRUCTORES
        
        /// <summary>
        /// Metodo de inicializacion de componentes de la clase
        /// </summary>
        /// <param name="oInstancia">Instancia de la que se tomaran los campos</param>
        protected void _InicializarComponentes(TBLbase oInstancia)
        {
            //si el diccionario de campos aun no esta instanciado
            if (this.CAMPOS == null)
            {
                //creamos una nueva instancia
                this.CAMPOS = new Dictionary<string, CampoTabla>();

                //tomamos el tipo de la instancia
                Type t = oInstancia.GetType();

                //recorremos el arreglo de campos de la clase
                foreach (FieldInfo c in t.GetFields())
                {
                    //si sel campo es del tipo CampoTabla
                    if (c.FieldType == typeof(CampoTabla))
                    {
                        //lo agregamos al diccionario de campos
                        this.CAMPOS.Add(c.Name, (CampoTabla)c.GetValue(this));
                    }
                }
            }
        }


        #endregion



        /// <summary>
        /// Devuelve una cadena con los nombres de los campos
        /// CAMPO0, CAMPO1, CAMPO2, ...
        /// </summary>
        public string Lista_de_campos
        {
            get
            {
                StringBuilder sbLista = new StringBuilder();

                foreach (CampoTabla oCampo in CAMPOS.Values)
                {
                    if (sbLista.ToString() == string.Empty) sbLista.Append(oCampo.cNombre);
                    else sbLista.Append(", ").Append(oCampo.cNombre);
                }

                return sbLista.ToString();
            }
        }

        /// <summary>
        /// Devuelve una cadena con los nombres de los campos con alias de la incluido
        /// TABLA.CAMPO0, TABLA.CAMPO1, TABLA.CAMPO2, ...
        /// </summary>
        public string Lista_de_campos_tabla
        {
            get
            {
                StringBuilder sbLista = new StringBuilder();

                foreach (CampoTabla oCampo in CAMPOS.Values)
                {
                    if (sbLista.Length.Equals(0)) sbLista.Append(GetNombreTabla).Append(".").Append(oCampo.cNombre);
                    else sbLista.Append(", ").Append(GetNombreTabla).Append(".").Append(oCampo.cNombre);
                }

                return sbLista.ToString();
            }
        }

        /// <summary>
        /// Devuelve el comando de seleccion base de la tabla
        /// SELECT TABLA.CAMPO0, TABLA.CAMPO1, ... FROM TABLA
        /// </summary>
        public string Get_select_basico
        {
            get
            {
                //formateamos el comando y lo devolvemos
                return string.Format(SELECT_BASICO
                                        , string.Empty
                                        , Lista_de_campos_tabla
                                        , GetNombreTabla
                                        );
            }
        }

        /// <summary>
        /// / <summary>
        /// Devuelve el comando de seleccion base de la tabla 
        /// SELECT DISTINCT TABLA.CAMPO0, TABLA.CAMPO1, ... FROM TABLA
        /// </summary>
        public string Get_select_distinct
        {
            get
            {
                //formateamos el comando y lo devolvemos
                return string.Format(SELECT_BASICO
                                        , "DISTINCT"
                                        , Lista_de_campos_tabla
                                        , GetNombreTabla
                                        );
            }
                
        }

        /// <summary>
        /// Devuelve el comando de insercion base de la tabla
        /// INSERT INTO TABLA (CAMPO0, CAMPO1, CAMPO2,...) VALUES({0})
        /// </summary>
        public string Get_insert_basico
        {
            get
            {
                //concatenamos la lista de campos NO autogenerados
                StringBuilder sbCampos = new StringBuilder();
                foreach (CampoTabla oCampo in CAMPOS.Values)
                {
                    if (!oCampo.bAutoGenerado)
                    {
                        if (sbCampos.ToString() == string.Empty) sbCampos.Append(oCampo.cNombre);
                        else sbCampos.Append(", ").Append(oCampo.cNombre);
                    }   
                }

                //formateamos el comando y lo devolvemos
                return string.Format(__INSERT_SQL
                                        , GetNombreTabla
                                        , sbCampos.ToString()
                                        , "{0}"
                                        );
            }
        }

        /// <summary>
        /// Devuelve el comando de insercion base de la tabla con valores parametros
        /// INSERT INTO TABLA (CAMPO0, CAMPO1,...) VALUES(@CAMPO0, @CAMPO1,...)
        /// </summary>
        public string Get_insert_parametros
        {
            get
            {
                //concatenamos la lista de campos NO autogenerados
                StringBuilder sbCampos = new StringBuilder();
                StringBuilder sbValores = new StringBuilder();
                int c = 0;

                foreach (CampoTabla oCampo in CAMPOS.Values)
                {
                    if (!oCampo.bAutoGenerado)
                    {
                        if (sbCampos.ToString().Equals(string.Empty)) sbCampos.Append(oCampo.cNombre);
                        else sbCampos.Append(", ").Append(oCampo.cNombre);

                        if (sbValores.ToString().Equals(string.Empty))
                            if (oCampo.tTipo.Equals(typeof(string)) || oCampo.tTipo.Equals(typeof(bool)))
                                sbValores.Append("'{" + c.ToString() + "}' ");
                            else sbValores.Append("{" + c.ToString() + "} ");
                        else
                            if (oCampo.tTipo.Equals(typeof(string)) || oCampo.tTipo.Equals(typeof(bool)))
                                sbValores.Append(", '{" + c.ToString() + "}' ");
                            else sbValores.Append(", {" + c.ToString() + "} ");

                        c += 1;
                    }
                }

                //formateamos el comando y lo devolvemos
                return string.Format(__INSERT_SQL
                                        , GetNombreTabla
                                        , sbCampos.ToString()
                                        , sbValores.ToString()
                                        );
            }
        }
        
        /// <summary>
        /// Devuelve el comando de actualizacion base de la tabla
        /// UPDATE TABLA SET CAMPO0 = {0}, CAMPO1 = {1}, ... WHERE {#campos+1}
        /// </summary>
        public string Get_update_basico
        {
            get
            {
                StringBuilder sbLista = new StringBuilder();
                int c = 0;

                //recorremos los campos de la tabla
                foreach (CampoTabla cCampo in CAMPOS.Values)
                {
                    //si el tipo de datos es string
                    if (cCampo.tTipo == typeof(string))
                    {
                        if (sbLista.ToString() == string.Empty) sbLista.Append(cCampo.cNombre).Append(" = '{" + c++.ToString() + "}'");
                        else sbLista.Append(", ").Append(cCampo.cNombre).Append(" = '{" + c++.ToString() + "}'");
                    }
                    else
                    {
                        //sino, directo
                        if (sbLista.ToString() == string.Empty) sbLista.Append(cCampo.cNombre).Append(" = {" + c++.ToString() + "}");
                        else sbLista.Append(", ").Append(cCampo.cNombre).Append(" = {" + c++.ToString() + "}");
                    }
                    
                }

                //formateamos el comando y lo devolvemos
                return string.Format(__UPDATE_SQL
                                       , GetNombreTabla
                                       , sbLista.ToString()
                                       );
            }
        }

        /// <summary>
        /// Devuelve el comando de actualizacion base de la tabla con parametros
        /// UPDATE TABLA SET CAMPO0 = @CAMPO0, CAMPO1 = @CAMPO1, ... WHERE {0}
        /// </summary>
        public string Get_update_parametros
        {
            get
            {
                StringBuilder sbComando = new StringBuilder();
                int c = 0;


                //recorremos los campos de la tabla 
                foreach (CampoTabla oCampo in CAMPOS.Values)
                {
                    if (sbComando.ToString() == string.Empty)
                        if (oCampo.tTipo == typeof(string) || oCampo.tTipo == typeof(bool))
                            sbComando.Append(oCampo.cNombre).Append(" = '{").Append(c.ToString()).Append("}'");
                        else
                            sbComando.Append(oCampo.cNombre).Append(" = {").Append(c.ToString()).Append("}");

                    else
                        if (oCampo.tTipo == typeof(string) || oCampo.tTipo == typeof(bool))
                            sbComando.Append(", ").Append(oCampo.cNombre).Append(" = '{").Append(c.ToString()).Append("}'");
                        else
                            sbComando.Append(", ").Append(oCampo.cNombre).Append(" = {").Append(c.ToString()).Append("}");

                    //incrementamos el contador de campos
                    c+= 1;
                }

                
                //formateamos el comando y lo devolvemos
                return string.Format(__UPDATE_SQL
                                       , GetNombreTabla
                                       , sbComando.ToString()
                                       );

                //return Get_update_basico;
            }
        }

        /// <summary>
        /// Devuelve el comando de eliminacion base de la tabla
        /// DELETE FROM TABLA WHERE {0}
        /// </summary>
        public string Get_delete_basico
        {
            get
            {
                //formateamos el comando y lo devolvemos
                return string.Format(__DELETE_SQL
                                       , GetNombreTabla
                                       );
            }
        }

        /// <summary>
        /// Devuelve la sentencia de busqueda con filtro por el campo [ID]
        /// SELECT TABLA.CAMPO0, TABLA.CAMPO1, ... WHERE TABLA.ID = {0}
        /// </summary>
        public string Get_buscar_por_id
        {
            get
            {
                return string.Format("{0} {1}", Get_select_basico
                                        , string.Format(__FILTRO_BASICO_INT
                                                        , GetNombreTabla
                                                        , "ID ", "{0}"
                                                        )
                                        );
            }
        }

        /// <summary>
        /// Devuelve la sentencia de busqueda con filtro por el campo [DESCRIPCION]
        /// SELECT TABLA.CAMPO0, TABLA.CAMPO1, ... WHERE TABLA.DESCRIPCION LIKE '%{0}%'
        /// </summary>
        public string Get_buscar_por_descripcion
        {
            get
            {
                return string.Format("{0} {1}", Get_select_basico
                                        , string.Format(__FILTRO_BASICO_STRING
                                                        , GetNombreTabla
                                                        , "DESCRIPCION"
                                                        , "{0}"
                                                        )
                                        );
            }
        }

        /// <summary>
        /// Devuelve la cadena WHERE complementaria para campos de tipo STRING
        /// WHERE TABLA.{0} LIKE '%{1}%'
        /// </summary>
        public string Get_filtro_where_string
        {
            get
            {
                return string.Format(__FILTRO_BASICO_STRING
                                        , GetNombreTabla
                                        , "{0}"
                                        , "{1}"
                                        );
            }
        }

        /// <summary>
        /// Devuelve la cadena WHERE complementaria para campos de tipo INT
        /// WHERE TABLA.{0} = {1}
        /// </summary>
        public string Get_filtro_where_int
        {
            get
            {
                return string.Format(__FILTRO_BASICO_INT
                                        , GetNombreTabla
                                        , "{0}"
                                        , "{1}"
                                        );
            }
        }

        /// <summary>
        /// Devuelve el nombre de la tabla manejada
        /// </summary>
        public abstract string GetNombreTabla{get;}

        /// <summary>
        /// Devuelve el comando de creacion de la tabla
        /// </summary>
        public virtual string Get_create_tabla()
        { return string.Empty;  }

        /// <summary>
        /// Devuelve el comando de eliminacion de la tabla
        /// </summary>
        public virtual string Get_drop_tabla(){
            return string.Format(DROP_SQL, GetNombreTabla);
        }
    
    }
}
